#include "YXThreadPool.h"
#include "YXLog.h"

#include <stdlib.h>
#include <string.h>

ThreadPool *yxThreadPoolCreate(int threadNum) {
    ThreadPool *pool = malloc(sizeof(ThreadPool));
    pool->threads    = (pthread_t *) malloc(sizeof(pthread_t) * threadNum);
    pool->task_list  = linked_list_create();
    pool->thread_num = threadNum;
    pool->shutdown   = 0;

    pthread_mutex_init(&pool->lock, NULL);
    pthread_cond_init(&pool->cond, NULL);

    for (int i = 0; i < threadNum; i++) {
        if (pthread_create(&pool->threads[i], NULL, yxThreadFunction, pool) != 0) {
            logErrno();
            exit(EXIT_FAILURE);
        }
    }

    logInfo("Thread pool created with %d threads", threadNum);
    return pool;
}


void yxThreadFunction(ThreadPool *pool) {
    Task *task;

    while (1) {
        pthread_mutex_lock(&pool->lock);
        while (pool->task_list->size == 0) {
            pthread_cond_wait(&pool->cond, &pool->lock);
        }
        task = linked_list_pop_l(pool->task_list);
        pthread_mutex_unlock(&pool->lock);

        task->function(task->arg);
        free(task);
    }
}

void yxThreadPoolAddTask(ThreadPool *pool, void (*function)(void *), void *arg) {
    Task *task     = malloc(sizeof(Task));
    task->function = function;
    task->arg      = arg;

    pthread_mutex_lock(&pool->lock);
    linked_list_add_r(pool->task_list, task);
    pthread_cond_signal(&pool->cond);
    pthread_mutex_unlock(&pool->lock);
}
